package validation.jexp;

import com.jgoodies.forms.builder.PanelBuilder;
import com.jgoodies.forms.factories.ButtonBarFactory;
import com.jgoodies.forms.layout.CellConstraints;
import com.jgoodies.forms.layout.FormLayout;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.text.JTextComponent;
import java.awt.event.ActionEvent;

/**
 * Builds an editor that copies data from the domain back and forth.
 * This approach is known as the "copying" approach or "push/pull".<p>
 *
 * The event handling used to enable and disable the composer text field
 * is invoked by a ChangeListener that hooks into the classical check box.
 * Note that this lacks the domain logic, where the composer is set to
 * <code>null</code> if the classical property is set to false.
 * This logic is deferred until the component values are written to the
 * edited Album via <code>#updateModel</code> when OK is pressed.
 *
 * @author Karsten Lentzsch
 * @version $Revision: 1.6 $
 */
public class EditorCopyingExample {

    private final Album editedAlbum;
    private JTextComponent titleField;
    private JTextComponent artistField;
    private JCheckBox classicalBox;
    private JTextComponent composerField;
    private JButton okButton;
    private JButton cancelButton;
    private JButton resetButton;

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel("com.jgoodies.looks.plastic.PlasticXPLookAndFeel");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        JFrame frame = new JFrame();
        frame.setTitle("Binding Tutorial::Editor(copying)");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        EditorCopyingExample example = new EditorCopyingExample();
        JComponent panel = example.build();
        example.updateView();
        frame.getContentPane().add(panel);
        frame.pack();
        JGoodiesValidationUtils.locateOnScreenCenter(frame);
        frame.setVisible(true);
    }

    public EditorCopyingExample() {
        this(Album.ALBUM1);
    }

    public EditorCopyingExample(Album album) {
        this.editedAlbum = album;
    }

    private void initComponents() {
        titleField = new JTextField();
        artistField = new JTextField();
        classicalBox = new JCheckBox("Classical");
        composerField = new JTextField();
        okButton = new JButton(new OkAction());
        cancelButton = new JButton(new CancelAction());
        resetButton = new JButton(new ResetAction());
        updateComposerField();
    }

    private void initEventHandling() {
        classicalBox.addChangeListener(new ClassicalChangeHandler());
        editedAlbum.addPropertyChangeListener(TutorialUtils.createDebugPropertyChangeListener());
    }

    private void updateView() {
        titleField.setText(editedAlbum.getTitle());
        artistField.setText(editedAlbum.getArtist());
        classicalBox.setSelected(editedAlbum.isClassical());
        composerField.setText(editedAlbum.getComposer());
    }

    private void updateModel() {
        editedAlbum.setTitle(titleField.getText());
        editedAlbum.setArtist(artistField.getText());
        editedAlbum.setClassical(classicalBox.isSelected());
        editedAlbum.setComposer(composerField.getText());
    }

    public JComponent build() {
        initComponents();
        initEventHandling();
        FormLayout formLayout = new FormLayout(
                "right:pref, 3dlu, 150dlu:grow",
                "p, 3dlu, p, 3dlu, p, 3dlu, p, 9dlu, p");

        PanelBuilder builder = new PanelBuilder(formLayout);
        builder.setDefaultDialogBorder();
        CellConstraints cc = new CellConstraints();
        builder.addLabel("Title", cc.xy(1, 1));
        builder.add(titleField, cc.xy(3, 1));
        builder.addLabel("Artist", cc.xy(1, 3));
        builder.add(artistField, cc.xy(3, 3));
        builder.add(classicalBox, cc.xy(3, 5));
        builder.addLabel("Composer", cc.xy(1, 7));
        builder.add(composerField, cc.xy(3, 7));
        builder.add(buildButtonBar(), cc.xyw(1, 9, 3));

        return builder.getPanel();
    }

    private JComponent buildButtonBar() {
        return ButtonBarFactory.buildRightAlignedBar(okButton, cancelButton, resetButton);
    }

    private void updateComposerField() {
        boolean composerEnabled = classicalBox.isSelected();
        composerField.setEnabled(composerEnabled);
        if (!composerEnabled) {
            composerField.setText("");
        }
    }

    private class ClassicalChangeHandler implements ChangeListener {
        @Override
        public void stateChanged(ChangeEvent e) {
            updateComposerField();
        }
    }

    private final class OkAction extends AbstractAction {
        private OkAction() {
            super("OK");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            updateModel();
            System.out.println(editedAlbum);
            System.exit(0);
        }
    }

    private final class CancelAction extends AbstractAction {
        private CancelAction() {
            super("Cancel");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println(editedAlbum);
            System.exit(0);
        }
    }

    private final class ResetAction extends AbstractAction {
        private ResetAction() {
            super("Reset");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            updateView();
            System.out.println(editedAlbum);
        }
    }
}
